package com.express.util.wx;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import com.express.conf.WechatConfig;
import com.express.entity.UserOrders;
import com.express.entity.WxUser;
import com.express.entity.wx.AccessToken;
import com.express.entity.wx.TemplateData;
import com.express.entity.wx.WxTemplate;
import com.express.mybatis.Result;
import com.express.util.DateUtils;
import com.express.util.HttpUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;

public class WeixinUtil {

  private static Logger log = LoggerFactory.getLogger(WeixinUtil.class);
  public static final String getTokenUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";
  public static final String refresh_token_url = "https://api.weixin.qq.com/sns/oauth2/refresh_token?grant_type=client_credential&appid=APPID&secret=APPSECRET";
  public static final String refresh_auth_token_url = "https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=APPID&grant_type=refresh_token&refresh_token=REFRESH_TOKEN";
  public static final String getAuthTokenUrl = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=APPSECRET&code=CODE&grant_type=authorization_code";
  public static final String sendTemplateMessage_url = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=ACCESS_TOKEN";
  public static Map<String, String> mapToken = new HashMap();

  /**
   * 获取微信accessToken
   * @param appid
   * @param appsecret
   * @return
   */
  public static AccessToken getAccessToken(String appid, String appsecret) {
    AccessToken accessToken = null;
    log.info("获取token参数:appid:{},appsecret:{}", appid ,appsecret);
    boolean isLoad = false;
    if ((mapToken.containsKey("token")) && (mapToken.containsKey("expiresIn")) && (mapToken.containsKey("date"))) {
      long nowDate = new Date().getTime();
      long oldDate = Long.valueOf((String) mapToken.get("date")).longValue();
      if (((nowDate - oldDate) / 1000L > 600L) || ((nowDate - oldDate) / 1000L > Long.valueOf((String) mapToken.get("expiresIn")).longValue())) {
        log.info("已超过10分中 重新获取assessToken");
        isLoad = true;
      }
    } else {
      isLoad = true;
    }
    if (isLoad) {
      String requestUrl = getTokenUrl.replace("APPID", appid).replace("APPSECRET", appsecret);
      log.info("请求地址:{}", requestUrl);
      String ret = HttpUtils.httpGet(requestUrl, new HashMap<>(), "utf-8");
      JSONObject json = JSON.parseObject(ret);
      if (null != ret) {
        try {
          log.info("返回结果:{}",json);
          accessToken = new AccessToken();
          accessToken.setToken(json.getString("access_token"));
          accessToken.setExpiresIn(json.getIntValue("expires_in"));
          // 缓存10分钟
          mapToken.put("token", json.getString("access_token"));
          mapToken.put("expiresIn", json.getIntValue("expires_in") + "");
          // 过期时间
          mapToken.put("date", new Date().getTime() + "");
        } catch (JSONException e) {
          accessToken = null;
          log.error("获取token失败 errcode:{} errmsg:{}", Integer.valueOf(json.getIntValue("errcode")), json.getString("errmsg"));
          e.printStackTrace();
        }
      }
    } else {
      accessToken = new AccessToken();
      accessToken.setToken((String) mapToken.get("token"));
      accessToken.setExpiresIn(Integer.valueOf((String) mapToken.get("expiresIn")).intValue());
    }
    log.info("not null " + JSON.toJSONString(accessToken));
    return accessToken;
  }

  /**
   * 调用微信api获取用户信息
   * @param accessToken
   * @param openId
   * @return
   */
  public static WxUser getUserInfo(String accessToken, String openId) {
    WxUser weixinUserInfo = null;
    String requestUrl = "https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN";
    requestUrl = requestUrl.replace("ACCESS_TOKEN", accessToken).replace("OPENID", openId);
    String ret = HttpUtils.httpGet(requestUrl, new HashMap<>(), "utf-8");
    JSONObject jsonObject = JSON.parseObject(ret);
    if (null != jsonObject && !jsonObject.containsKey("errcode")) {
      try {
        weixinUserInfo = new WxUser();
        weixinUserInfo.setOpenId(jsonObject.getString("openid"));
        weixinUserInfo.setSubscribe(jsonObject.getIntValue("subscribe"));
        weixinUserInfo.setSubscribeTime(jsonObject.getString("subscribe_time"));
        weixinUserInfo.setNickName(jsonObject.getString("nickname"));
        weixinUserInfo.setSex(jsonObject.getIntValue("sex"));
        weixinUserInfo.setCountry(jsonObject.getString("country"));
        weixinUserInfo.setProvince(jsonObject.getString("province"));
        weixinUserInfo.setCity(jsonObject.getString("city"));
        weixinUserInfo.setLanguage(jsonObject.getString("language"));
        weixinUserInfo.setHeadImgUrl(jsonObject.getString("headimgurl"));
      } catch (Exception e) {
        if (0 == weixinUserInfo.getSubscribe()) {
          log.error("用户{}已取消关注", weixinUserInfo.getOpenId());
        } else {
          int errorCode = jsonObject.getIntValue("errcode");
          String errorMsg = jsonObject.getString("errmsg");
          log.error("获取用户信息失败 errcode:{} errmsg:{}", Integer.valueOf(errorCode), errorMsg);
        }
      }
    } else {
      log.info("清空token");
      mapToken.clear();
      log.info("检查token是否过期:{}",jsonObject);
      return null;
    }
    return weixinUserInfo;
  }

  /**
   * 刷新
   * @param refreshToken
   * @param openId
   * @return
   */
  public static String  refreshAuthToken(String refreshToken,String openId){
    String requestUrl = refresh_auth_token_url.replace("REFRESH_TOKEN", refreshToken).replace("OPENID", openId);
    String ret = HttpUtils.httpGet(requestUrl, new HashMap<>(), "utf-8");
    return ret;
  }

  /**
   * 组装消息模板
   * @param template_id_short
   * @param t
   * @param m
   * @return
   * @throws Exception
   */
  public static int sendMessageBefore(String template_id_short, WxTemplate t, Map<String, TemplateData> m)
          throws Exception {
    AccessToken token = null;
    token = getAccessToken(WechatConfig.APP_ID, WechatConfig.APP_SECRET);
    if ((template_id_short != null) && (!"".equals(template_id_short))) {
      WxTemplate template = getTemplate(template_id_short, "");
      t.setTemplate_id(template.getTemplate_id());
    }
    return sendMessage(t, token.getToken());
  }

  /**
   * 发送消息模板
   * @param template_id_short
   * @param openid
   * @return
   */
  public static WxTemplate getTemplate(String template_id_short, String openid) {
    WxTemplate tmp = new WxTemplate();
    tmp.setTemplate_id(template_id_short);
    tmp.setTouser(openid);
    Map<String, TemplateData> map = new HashMap();
    tmp.setData(map);
    return tmp;
  }

  /**
   *  发送消息模板
   * @param t
   * @param accessToken
   * @return
   * @throws Exception
   */
  public static int sendMessage(WxTemplate t, String accessToken)
          throws Exception {
    int result = 0;
    log.info("发送模板消息的token :" + accessToken);

    String url = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=ACCESS_TOKEN".replace("ACCESS_TOKEN", accessToken);

    String jsonMenu = JSON.toJSONString(t);
    log.info("模板消息内容" + jsonMenu);
    Map<String, Object> map = JSON.parseObject(jsonMenu);
    LinkedHashMap<String, Object> params = new LinkedHashMap();
    for (Map.Entry<String, Object> entry : map.entrySet()) {
      params.put(entry.getKey(), entry.getValue());
    }
    String ret = HttpUtils.httpsPostJson(url, JSON.toJSONString(params),  "utf-8");
    JSONObject jsonObject = JSON.parseObject(ret);
    if ((null != jsonObject) &&
            (0 != jsonObject.getIntValue("errcode"))) {
      result = jsonObject.getIntValue("errcode");
      log.error("发送模板消息失败 errcode:{} errmsg:{}", Integer.valueOf(jsonObject.getIntValue("errcode")), jsonObject.getString("errmsg"));
      log.info("清空token");
      mapToken.clear();
    }
    return result;
  }

  /**
   * 初始化要发送的模版消息
   * @param openid
   * @param param
   */
  public static void sendDataToTemp(String openid,String msgId,Map<String,String> param){
    try {
      // 发送微信模版消息
      AccessToken accessToken = WeixinUtil.getAccessToken(WechatConfig.APP_ID, WechatConfig.APP_SECRET);
      WxTemplate template = WeixinUtil.getTemplate(msgId, openid);
      Map<String, TemplateData> map = new HashMap();
      map.put("first", new TemplateData(param.get("first"), "#0000FF"));
      for (String str : param.keySet()) {
        map.put(str, new TemplateData(param.get(str), "#000000"));
      }
      map.put("remark", new TemplateData(param.get("remark"), "#0000FF"));
      template.setData(map);
      int re = WeixinUtil.sendMessage(template, accessToken.getToken());
      if (re == 0) {
        log.info("发送消息成功");
      }
    } catch (Exception e) {
      e.printStackTrace();
    }
  }

  public static void main(String[] args) {
    try {
      String token = getAccessToken(WechatConfig.APP_ID, WechatConfig.APP_SECRET).getToken();
//      String token = "39_pwONtnP2TzA5VVTuChbnrYje7dh4rTL9_uo7QhSp15b5FyD2G5xs1S1jv_qHRFD7IgYvp4GcjqWWAOJykQ75hAkZlie3SReHeOWcUY_BvG8QdSvaA8ugB6h4dkBtdo9VePLlv0_VvuAjAMYiIKQbACAWYE";
      WxTemplate tmp = getTemplate(WechatConfig.WEIXIN_MSGID, "oaDIQ6QB-xDRCRBtDaX2q5aHK5VI");
      Map<String, TemplateData> map = new HashMap();
      map.put("first", new TemplateData("你有新的快件信息。", "#0000FF"));
      map.put("keyword1", new TemplateData("test11", "#000000"));
      map.put("keyword2", new TemplateData("广州增城", "#000000"));
      map.put("keyword3", new TemplateData("2020-11-11 13:30:12", "#000000"));
//      map.put("keyword4", new TemplateData("��999", "#E41C1C"));

      map.put("remark", new TemplateData("您的快件已接收，感谢您对本物流的支持，欢迎您下次使用。", "#0000FF"));

      tmp.setData(map);
      int re = sendMessage(tmp, token);
      if (re == 0) {
        log.info("成功!");
      }
//      List list = new ArrayList<>();
//      WxUser usr = new WxUser();
//      usr.setOpenId("222");
//      WxUser usr1 = new WxUser();
//      usr1.setOpenId("333");
//      WxUser usr2 = new WxUser();
//      usr2.setOpenId("4444");
//      list.add(usr);
//      list.add(usr1);
//      list.add(usr2);
//      int temp = Optional.ofNullable(list).map(u->u.get(0).getOpenId().orElse(null);
//      log.info("有"+temp);
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}